package com.qq.多线程.线程通信.存钱取钱;


/*
 
	什么是线程通信、如何实现？
	所谓线程通信就是线程间相互发送数据，线程间共享一个资源即可实现线程通信
	
	线程通信常见形式
	通过共享一个数据的方式实现。
	根据共享数据的情况决定自己该怎么做，以及通知其他线程怎么做。
	
	线程通信实际应用场景
	生产者与消费者模型：生产者线程负责生产数据，消费者线程负责消费生产者产生的数据。
	要求：生产者线程生产完数据后唤醒消费者，然后等待自己，消费者消费完该数据后唤醒生产者，然后等待自己。

	线程通信的前提：
	线程通信通常是在多个线程操作同一个共享资源的时候需要进行通信且要  保证线程安全！！
	多个线程同时访问同一个共享资源且存在修改该资源时就会存在安全问题
	所以我们要先使用同步方法，使线程同步后，再进行线程通信。
	
	Object类的等待和唤醒方法：
	void wait​()			让当前线程等待并释放所占锁，直到另一个线程调用notify()方法或 notifyAll()方法
	void notify​()		随机唤醒正在等待的单个线程 
	void notifyAll​()	唤醒正在等待的所有线程 
	注:
	官方希望任何对象都可以调用，所以放在object类！！
	我们要用锁对象调用唤醒等待方法，因为只有锁对象知道谁在占它，谁等着它唤醒（也就是任何对象都可以成为锁对象）
	上述方法应该使用当前同步锁对象进行调用。
	先唤醒别的线程再等待，不然自己都晕了，唤醒不了别人
	
	注：从wait()状态被唤醒的线程，第一次抢到锁只是为了从上次wait()处开始，执行完同步方法。
							第二次抢锁才是重新执行同步方法。
 */

public class Test {
//	需求：使用3个爸爸存钱(生产者)2个孩子取钱(消费者)模拟线程通信思想(一存10万，一取10万)
	public static void main(String[] args) {
//		1.创建账户对象，代表五个人共同操作的账户
		Account acc = new Account("ICBC-112",0);
		
//		2.创建两个取钱线程代表小明和小红
		new DrawThread(acc,"小明").start();
		new DrawThread(acc,"小红").start();
		
//		3.创建两个存钱线程代表：亲爹，干爹，岳父。
		new DepositThread(acc,"亲爹").start();
		new DepositThread(acc,"干爹").start();
		new DepositThread(acc,"岳父").start();
		
	}

}
